#ifndef _PLATFORM_H_CSEAPI_
#define _PLATFORM_H_CSEAPI_

#include "CseApi/setup.h"

#ifdef _DEBUG
  #ifndef DEBUG
    #define DEBUG
  #endif
#endif

#ifdef DEBUG
  #ifndef _DEBUG
    #define _DEBUG
  #endif
#endif

#ifdef WINCE
  #undef  WINVER
  #define WINVER _WIN32_WCE

  #ifndef VC_EXTRALEAN
    #define VC_EXTRALEAN
  #endif

  #include <ceconfig.h>
  #if defined(WIN32_PLATFORM_PSPC) || defined(WIN32_PLATFORM_WFSP)
    #define SHELL_AYGSHELL
  #endif

  #if defined(WIN32_PLATFORM_PSPC) || defined(WIN32_PLATFORM_WFSP)
    #ifndef _DEVICE_RESOLUTION_AWARE
      #define _DEVICE_RESOLUTION_AWARE
    #endif
  #endif

  #ifdef _DEVICE_RESOLUTION_AWARE
    #include "DeviceResolutionAware.h"
  #endif

  #include <aygshell.h>
  #pragma comment(lib, "aygshell.lib") 

  #if (_WIN32_WCE < 0x500) && ( defined(WIN32_PLATFORM_PSPC) || defined(WIN32_PLATFORM_WFSP) )
    #pragma comment(lib, "ccrtrtti.lib")
    #ifdef _X86_
        #if defined(_DEBUG)
            #pragma comment(lib, "libcmtx86d.lib")
        #else
            #pragma comment(lib, "libcmtx86.lib")
        #endif
    #endif
  #endif

  #include <altcecrt.h>

  #undef  CSE_USE_UNICODE
  #define CSE_USE_UNICODE          1   // WinCE only support unicode
#endif

#include "CseApi/CseTypes.h"

#ifdef CSEAPI_EXPORTS              // Export CSE kernel API
  #define CSE_IMPEXP_IN            CSE_EXPORT
#elif CSE_STATIC_LINK              // Static link CSE kernel
  #define CSE_IMPEXP_IN
#else                              // Import CSE kernel from DLL
  #define CSE_IMPEXP_IN            CSE_IMPORT
#endif
#define CSE_IMPEXP_OUT             CSE_EXPORT

#define CSE_STDCALL                __stdcall

#include <limits.h>
#include <stdlib.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>

#define CSE_CONCAT(text, post)     text ## post

#ifndef _T
  #if !CSE_USE_UNICODE
    #define _T(x) x
  #else
    #define _T(x)                  CSE_CONCAT(L,x)
  #endif
#endif

#define CHECK_TRUE(b)              Cse_AssertMsg2(b,__LINE__,_T(__FILE__))
#define CHECK_MSG(b,desc)          Cse_AssertMsg(b,desc)
#define WAIT_TO_DO()               throw Cse_WaitToDo(__LINE__,_T(__FILE__))

#ifdef _DEBUG
  #define ASSERT_MSG(b,desc)       Cse_AssertMsg(b,desc)
  #define ASSERT_TRUE(b)           CHECK_TRUE(b)
#else
  #define ASSERT_MSG
  #define ASSERT_TRUE
#endif

#if defined(__WINDOWS__)
  #if defined(_MSC_VER) && _MSC_VER >= 1200 // support VC6 and later version
    #pragma warning(disable: 4996)

    #define CSE_EXPORT             __declspec(dllexport)
    #define CSE_IMPORT             __declspec(dllimport)
    
    #define CseLongLongFmtSpec     _T("I64")
  #else
    #error "Compiler not support yet!"
  #endif
#endif

#define CSE_INT_SIZE               sizeof(TInt)

// if sizeof(TInt) != sizeof(void *), error will report at compile time
// CSE system use TInt to hold symbol address also!
struct TInt_same_size_to { int a_pointer: sizeof(TInt) == sizeof(void *); };

// if sizeof(TInt) is not 4 or 8, error will report at compile time
// sizeof(TInt) == 4 is NORMAL_INT_SYS, 8 is LARGE_INT_SYS
struct TInt_must_be { int TInt32_or_TInt64: sizeof(TInt)==4 || sizeof(TInt)==8;};

#ifndef SIZE_T_MAX
  #define SIZE_T_MAX               ((size_t) -1)
#endif

#if CSE_USE_ERR_LOG
  #if defined(_UNICODE)
    #define LOG_MSG                wprintf
  #else
    #define LOG_MSG                printf
  #endif
#else
  #define LOG_MSG
#endif

#ifdef _DEBUG
  #define STATIC
  #define LOG_DBG_MSG              LOG_MSG
#else
  #define STATIC                   static
  #define LOG_DBG_MSG
#endif

#ifdef _UNICODE
  #define PRINTF                   wprintf
  #define STRCPY                   wcscpy
  #define STRNCPY                  wcsncpy
  #define STRSTR                   wcsstr
  #define STRCMP                   wcscmp
  #define SPRINTF                  swprintf
  #define STRLEN                   wcslen
  #define STRCAT                   wcscat
  #define SCANF                    wscanf
  #define SSCANF                   swscanf
  #define GETS                     _getws
#else
  #define PRINTF                   printf
  #define STRCPY                   strcpy
  #define STRNCPY                  strncpy
  #define STRSTR                   strstr
  #define STRCMP                   strcmp
  #define SPRINTF                  sprintf
  #define STRLEN                   strlen
  #define STRCAT                   strcat
  #define SCANF                    scanf
  #define SSCANF                   sscanf
  #define GETS                     gets
#endif

class TCseException;  // forward declare
extern CSE_IMPEXP_IN void Cse_AssertMsg(int expr, const TXchar *msg);
extern CSE_IMPEXP_IN void Cse_AssertMsg2(int expr, int iLine, const TXchar *sFile);
extern CSE_IMPEXP_IN TCseException Cse_WaitToDo(int line, const TXchar *sFile);

extern CSE_IMPEXP_IN TInt32 READ_FLAG(TInt32 iFlag, int iOffset, int n);
extern CSE_IMPEXP_IN TInt32 MAKE_FLAG(TInt32 iFlag, TInt32 iValue, int iOffset, int n);

#define CUT_FROM                   20051206  // The date CSE V1 first released

#endif
